package dxunderground.chatbot.training;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import dxunderground.chatbot.Bot;
import dxunderground.chatbot.XMLFilter;
import dxunderground.chatbot.constants.MapConstants;
import dxunderground.chatbot.factories.BotFactory;
import dxunderground.chatbot.factories.MapFactory;

public class Training implements MapConstants, Runnable {
	public static void main(String[] args) throws JDOMException, IOException {
		InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("dxunderground/chatbot/properties/properties.xml");
		SAXBuilder builder = new SAXBuilder();
		Document doc = builder.build(in);

		Element properties = doc.getRootElement();

		File botHome = new File(properties.getChildText("botHome"));
		botHome.mkdirs();

		String personality = botHome.getAbsolutePath() + File.separator + properties.getChildText("personality");
		Bot bot = BotFactory.getBot(personality, false);
		File trainingInfo = new File(properties.getChildText("msnConvos"));

		File[] list = trainingInfo.listFiles(new XMLFilter());
		ExecutorService executorService = Executors.newFixedThreadPool(10);

		for (File file : list)
			executorService.submit(new Thread(new Training(file, bot), file.getName()));

		try {
			executorService.shutdown();
			while (!executorService.awaitTermination(5, TimeUnit.SECONDS))
				;
		} catch (InterruptedException e) {
		}

		bot.savePersonality(personality, false);
	}

	private File trainingFile;
	private Bot bot;

	public Training(File trainingFile, Bot bot) {
		this.trainingFile = trainingFile;
		this.bot = bot;
	}

	@Override
	public void run() {
		// TODO add more training
		try {
			oneResponseDeep(bot, trainingFile);
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void oneResponseDeep(Bot bot, File infoFile) throws JDOMException, IOException {
		SAXBuilder builder = new SAXBuilder();
		Document doc = builder.build(infoFile);

		Element elem = doc.getRootElement();
		clean(elem);
		Element curr = elem;
		Element prevRequest = null;
		String prevUserName = "";
		String prevSessionID = "";

		while (curr != null) {
			Map<Object, Object> map = getMessage(curr);
			String userName = (String) map.get(USER_NAME);
			String message = (String) map.get(MESSAGE);
			String sessionID = (String) map.get(SESSION_ID);

			// Only if messages are one level deep
			if (message != null && !message.equals("") && (!prevUserName.equals(userName) || prevUserName.equals("")) && (prevSessionID.equals(sessionID) || prevSessionID.equals(""))) {
				if (prevRequest != null)
					bot.addResponse(prevRequest, message);
				prevRequest = bot.addRequest(message);
				prevUserName = userName;
				prevSessionID = sessionID;
			} else {
				prevRequest = null;
				prevSessionID = "";
			}

			Element from = (Element) map.get(ELEMENT);
			curr = from;
		}
	}

	private Map<Object, Object> getMessage(Element elem) {
		Map<Object, Object> map = MapFactory.getMap();

		Element message = elem.getChild("Message");
		if (message != null) {
			Element from = message.getChild("From");
			Element user = from.getChild("User");
			Attribute userNameAttrib = user.getAttribute("FriendlyName");
			String userName = userNameAttrib.getValue();
			Element to = from.getChild("To");
			Element textElem = to.getChild("Text");
			String text = textElem.getTextNormalize();

			map.put(SESSION_ID, message.getAttributeValue(SESSION_ID));
			map.put(USER_NAME, userName);
			map.put(ELEMENT, from);
			map.put(MESSAGE, text);
		}
		return map;
	}

	private void clean(Element elem) {
		elem.removeAttribute("FirstSessionID");
		elem.removeAttribute("LastSessionID");
		elem.removeAttribute("Date");
		elem.removeAttribute("Time");
		elem.removeAttribute("DateTime");
		elem.removeAttribute("Style");
		for (Object child : elem.getChildren()) {
			clean((Element) child);
		}
	}
}